/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Negocio;

import BaseDatos.GestorBD;
import Util.GestorErrores;
import Util.Varios;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;

/**
 *
 * @author Javi
 */
public class Premisa implements ObjetoDatos{
    //Nombre de la tabla de la Base de Datos
    private String _sNombreTabla = "Premisas";
    //Descripción de la tabla de la Base de Datos
    private String _sDescripTabla = "Premisas";
    //Condición where
    private String sCondWhere = "";

    //Atributos de la tabla Premisas
    private int _iIdPremisa;
    private String _sTipoPremisa;
    private String _sTabla;
    private String _sCampo;
    private String _sValor;
    private String _sValorMin;
    private String _sValorMax;
    private int _iIdRegla;
    //El atributo tipo es un atributo auxiliar, no se guarda en la tabla
    //Se utiliza para indicar el tipo de datos que se está introduciendo y hacer las validaciones
    //pertinentes.
    private String _sTipoCampo;

    /*
     * Recupera todo el contenido de la tabla y lo devuelvo en 2 vectores. Uno con los nombres de los campos y
     * otro vector de vectores con los datos propiamente dichos (cada tupla de datos en un vector). El orden de los
     * campos de la fila es el mismo que el de los nombres de los campos.
     */
    public boolean selectAll ( Vector columnIdentifiers, Vector dataVector){
        String sCondicion = "";
        //Si hay alguna condición se añade a la sentencia
        if (this.sCondWhere.compareTo("") != 0)
            sCondicion = " WHERE " + this.sCondWhere;
        try {
            Statement st = GestorBD.getInstancia().getConexion().createStatement();
            ResultSet rs = st.executeQuery("SELECT IdRegla, IdPremisa, TipoPremisa, Tabla, Campo, Valor, ValorMin, ValorMax FROM " +
                    this._sNombreTabla + sCondicion + " ORDER BY IdRegla, IdPremisa");
            ResultSetMetaData metaDatos = rs.getMetaData();
            // Se obtiene el número de columnas.
            int numeroColumnas = metaDatos.getColumnCount();
            // Se obtiene cada una de las etiquetas para cada columna
            for (int i = 0; i < numeroColumnas; i++){
               // Nuevamente, para ResultSetMetaData la primera columna es la 1.
               columnIdentifiers.addElement( metaDatos.getColumnLabel(i + 1) );
            }

            while (rs.next()) {
                // Se crea un vector que será cada fila de la tabla.
                Vector fila = new Vector (numeroColumnas);

                // Se rellena cada posición del vector con una de las columnas de la tabla en base de datos.
                for (int i = 0; i < numeroColumnas; i++)
                    fila.addElement ( rs.getObject(i+1) ); // El primer indice en rs es el 1, no el cero, por eso se suma 1.

                // Se añade al modelo la fila completa.
                dataVector.addElement( fila );
            }
            rs.close();
            st.close();
            return true;
        }catch (SQLException e1){
            GestorErrores.getInstancia().getvErrores().add ( e1.getMessage() );
        }catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }

    /*
     * Inserta un registro en la tabla
     */
    public boolean insert ( ){
        if ( !validar () )
            return false;
        String sSQL = "INSERT INTO " + this._sNombreTabla + " (Tabla, Campo, Valor, ValorMin, ValorMax, TipoPremisa, IdRegla)" +
            " VALUES ('" +
            this._sTabla + "', '" + this._sCampo + "', '" + this._sValor + "', '" +
            this._sValorMin + "', '" + this._sValorMax + "', '" + this._sTipoPremisa + "', " + this._iIdRegla + ")";
        try {
            Statement st = GestorBD.getInstancia().getConexion().createStatement();
            st.execute(sSQL);
            st.close();

            //Recuperar y cargar en la clase el valor de la clave AUTONUMERICA generada por el motor de BD
            this._iIdPremisa = GestorBD.obtenerLastAutonumerico();
            return true;
        }catch (SQLException e1){
            GestorErrores.getInstancia().getvErrores().add ( e1.getMessage() );
        }catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }


    /*
     * Actualiza un registro en la entidad auxiliar
     */
    public boolean update ( ){
        if ( !validar () )
            return false;
        String sSQL = "UPDATE " + this._sNombreTabla + " SET Tabla = '" + this._sTabla + "', " +
            " Campo = '" + this._sCampo + "', " +
            " Valor = '" + this._sValor + "', " +
            " ValorMin = '" + this._sValorMin + "', " +
            " ValorMax = '" + this._sValorMax + "', " +
            " TipoPremisa = '" + this._sTipoPremisa + "', " +
            " IdRegla = " + this._iIdRegla + 
             " WHERE IdPremisa = " + this._iIdPremisa;
        try {
            Statement st = GestorBD.getInstancia().getConexion().createStatement();
            st.execute(sSQL);
            st.close();
            return true;
        }catch (SQLException e1){
            GestorErrores.getInstancia().getvErrores().add ( e1.getMessage() );
        }catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }

    /*
     * Si viene relleno el idpremisa y el idregla borra 1 único registro.
     * Si SOLO viene relleno el idRegla, borra todos los registros de la regla
     */
    public boolean delete (){
        String sSQL = "DELETE FROM " + this._sNombreTabla + " WHERE " +
             " IdRegla = " + this._iIdRegla;
        if (this._iIdPremisa != 0)
            sSQL += " AND IdPremisa = " + this._iIdPremisa;
        try {
            Statement st = GestorBD.getInstancia().getConexion().createStatement();
            st.execute(sSQL);
            st.close();
            return true;
        }catch (SQLException e1){
            GestorErrores.getInstancia().getvErrores().add ( e1.getMessage() );
        }catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }

    public boolean validar() {
        boolean bValorRelleno = false;
        boolean bValorMinOK = false;
        boolean bValorMaxOK = false;

        if ( this._iIdRegla == 0 )
            GestorErrores.getInstancia().getvErrores().add ("El Identificador de Regla es obligatorio");
        if ( this._sTipoPremisa.equals("") )
            GestorErrores.getInstancia().getvErrores().add ("El Tipo de Premisa es obligatorio");
        if ( this._sTabla.equals("") )
            GestorErrores.getInstancia().getvErrores().add ("El nombre de la tabla es obligatorio");
        if ( this._sCampo.equals("") )
            GestorErrores.getInstancia().getvErrores().add ("El nombre del campo es obligatorio");

        //Validar que se ha rellenado solo el campo Valor, o los 2 campos ValorMin y ValorMax
        if ( !this._sValor.equals("") ){
            bValorRelleno = true;
            if ( !this._sValorMin.equals("") || !this._sValorMax.equals("") )
                GestorErrores.getInstancia().getvErrores().add ("Debe rellenarse el campo Valor o bien los Valores Mínimo y Máximo");
        }else{
            bValorRelleno = false;
            if ( this._sValorMin.equals("") || this._sValorMax.equals("") ){
                GestorErrores.getInstancia().getvErrores().add ("Debe rellenarse el campo Valor o bien los Valores Mínimo y Máximo");
            }
        }
        //Validación de los campos en función del tipo de datos del campo.
        //Las validaciones SOLO se hacen CUANDO YA SE CONOCE EL TIPO DE DATOS DEL CAMPO
        //En los campos String lo único que hay que validar es que no vayan vacíos, y eso ya lo hemos hecho antes.
        //Los campos booleanos se tratan como los String (valdrán 'S' o 'N'). Idem que los String
        //Intento validar TODO lo que me hayan introducido
        if (! this._sTipoCampo.equals("")){
            if (!this._sValor.equals(""))
                if (!validaValor (this._sValor))
                    GestorErrores.getInstancia().getvErrores().add ("El campo Valor debe contener un tipo " + getDescripErrorTipo());
            if (!this._sValorMin.equals(""))
                if (!validaValor (this._sValorMin)){
                    GestorErrores.getInstancia().getvErrores().add ("El campo ValorMin debe contener un tipo "  + getDescripErrorTipo());
                    bValorMinOK = false;
                }else
                    bValorMinOK = true;
            if (!this._sValorMax.equals(""))
                if (!validaValor (this._sValorMax)){
                    GestorErrores.getInstancia().getvErrores().add ("El campo ValorMax debe contener un tipo "  + getDescripErrorTipo());
                    bValorMaxOK = false;
                }else
                    bValorMaxOK = true;
            if ( bValorMinOK && bValorMaxOK ){
                if ( ! validaMenorOIgual (this._sValorMin, this._sValorMax))
                    GestorErrores.getInstancia().getvErrores().add ("ValorMin debe ser menor o igual que ValorMax");
            }
        }
        return (GestorErrores.getInstancia().getvErrores().size () == 0);
    }

    private String getDescripErrorTipo (){
        if (this._sTipoCampo.equals("D"))
            return ("Date(DD/MM/AAAA)");
        else if (this._sTipoCampo.equals("I"))
            return ("Integer");
        else if (this._sTipoCampo.equals("B"))
            return ("Boolean");
        else if (this._sTipoCampo.equals("S"))
            return ("String");
        return "";
    }
    /**
     * Valida si el valor recibido (un String) contiene un valor conforme al tipo esperado
     * El valor pasado debe ir relleno, distinto de la sCadena vacía.
     * @param sValor
     * @return
     */private boolean validaValor( String sValor ){
        if (this._sTipoCampo.equals("D")){
            SimpleDateFormat formatoDelTexto = new SimpleDateFormat("dd/MM/yyyy");
            try {
                Date dFecha1 = formatoDelTexto.parse( sValor );
            } catch (ParseException ex) {
                return false;
            }
            return true;
        }else if (this._sTipoCampo.equals("I")){
            try {
                Integer.parseInt(sValor);
            }catch(NumberFormatException e){
                return false;
            }
            return true;
        }

        //PAra el resto de los tipos de datos
        return true;
    }

    /**
     * Valida si 2 valores son uno MENOR O IGUAL que el otro, teniendo en cuenta
     * el tipo de datos que se está considerando. Ambos valores deben venir rellenos y validados previamente.
     * @param sValorMin
     * @param sValorMax
     * @return
     */
    private boolean validaMenorOIgual (String sValorMin, String sValorMax){
        if (this._sTipoCampo.equals("D")){
            SimpleDateFormat formatoDelTexto = new SimpleDateFormat("dd/MM/yyyy");
            Date dFechaMin, dFechaMax;
            try {
                dFechaMin = formatoDelTexto.parse( sValorMin );
                dFechaMax = formatoDelTexto.parse( sValorMax );
            } catch (ParseException ex) {
                return false;
            }
            if ( dFechaMin.compareTo(dFechaMax) <= 0)
                return true;
            else
                return false;
        }else if (this._sTipoCampo.equals("I")){
            return ( Integer.parseInt (sValorMin) <= Integer.parseInt (sValorMax) );
        }

        //Para el resto de los tipos de datos
        return true;
    }

    public void vectorJTableAClavesClase(Vector columnIdentifiers, Vector dataRow) {
        this.inicializa();
        int iIndice = Varios.getPosCadena(columnIdentifiers, "IdPremisa");
        this._iIdPremisa = Integer.parseInt( dataRow.get(iIndice).toString() );
    }

    /**
     * Este método se utiliza en la parte de inferencia
     * @param columnIdentifiers
     * @param dataRow
     */
    public void vectorJTableAClase(Vector columnIdentifiers, Vector dataRow) {
        this.inicializa();
        int iIndice = Varios.getPosCadena(columnIdentifiers, "IdPremisa");
        this._iIdPremisa = Integer.parseInt( dataRow.get(iIndice).toString() );
        iIndice = Varios.getPosCadena(columnIdentifiers, "IdRegla");
        this._iIdRegla = Integer.parseInt( dataRow.get(iIndice).toString() );
        iIndice = Varios.getPosCadena(columnIdentifiers, "TipoPremisa");
        this._sTipoPremisa = dataRow.get(iIndice).toString();
        iIndice = Varios.getPosCadena(columnIdentifiers, "Tabla");
        this._sTabla = dataRow.get(iIndice).toString();
        iIndice = Varios.getPosCadena(columnIdentifiers, "Campo");
        this._sCampo = dataRow.get(iIndice).toString();
        iIndice = Varios.getPosCadena(columnIdentifiers, "Valor");
        this._sValor = dataRow.get(iIndice).toString();
        iIndice = Varios.getPosCadena(columnIdentifiers, "ValorMin");
        this._sValorMin = dataRow.get(iIndice).toString();
        iIndice = Varios.getPosCadena(columnIdentifiers, "ValorMax");
        this._sValorMax = dataRow.get(iIndice).toString();
    }


    public Vector claseAVectorJTable(Vector columnIdentifiers) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void recupera() {
        try {
            Statement st = GestorBD.getInstancia().getConexion().createStatement();
            ResultSet rs;
            rs = st.executeQuery("SELECT * FROM " + this._sNombreTabla + " WHERE " +
            " IdPremisa = " + this._iIdPremisa);
            if ( rs.next() ) {
                this._iIdPremisa = rs.getInt("idPremisa");
                this._sTabla = rs.getString("Tabla");
                this._sCampo = rs.getString("Campo");
                this._sValor = rs.getString("Valor");
                this._sValorMin = rs.getString("ValorMin");
                this._sValorMax = rs.getString("ValorMax");
                this._sTipoPremisa = rs.getString("TipoPremisa");
                this._iIdRegla = rs.getInt("IdRegla");
            }
            rs.close();
            st.close();

        }catch (SQLException e1){
            GestorErrores.getInstancia().getvErrores().add ( e1.getMessage() );
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void inicializa() {
        this._iIdPremisa = 0;
        this._sTipoPremisa ="";
        this._sTabla = "";
        this._sCampo = "";
        this._sValor = "";
        this._sValorMin = "";
        this._sValorMax ="";
        this._iIdRegla = 0;
        this._sTipoCampo = "";
    }

    public int getiIdPremisa() {
        return _iIdPremisa;
    }

    public void setiIdPremisa(int _iIdPremisa) {
        this._iIdPremisa = _iIdPremisa;
    }

    public int getiIdRegla() {
        return _iIdRegla;
    }

    public void setiIdRegla(int _iIdRegla) {
        this._iIdRegla = _iIdRegla;
    }

    public String getsCampo() {
        return _sCampo;
    }

    public void setsCampo(String _sCampo) {
        this._sCampo = _sCampo;
    }

    public String getsDescripTabla() {
        return _sDescripTabla;
    }

    public void setsDescripTabla(String _sDescripTabla) {
        this._sDescripTabla = _sDescripTabla;
    }

    public String getsNombreTabla() {
        return _sNombreTabla;
    }

    public void setsNombreTabla(String _sNombreTabla) {
        this._sNombreTabla = _sNombreTabla;
    }

    public String getsTabla() {
        return _sTabla;
    }

    public void setsTabla(String _sTabla) {
        this._sTabla = _sTabla;
    }

    public String getsValorMax() {
        return _sValorMax;
    }

    public void setsValorMax(String _sValorMax) {
        this._sValorMax = _sValorMax;
    }

    public String getsValorMin() {
        return _sValorMin;
    }

    public void setsValorMin(String _sValorMin) {
        this._sValorMin = _sValorMin;
    }

    public String getsValor() {
        return _sValor;
    }

    public void setsValor(String _sValor) {
        this._sValor = _sValor;
    }

    public String getsCondWhere() {
        return sCondWhere;
    }

    public void setsCondWhere(String sCondWhere) {
        this.sCondWhere = sCondWhere;
    }

    public String getsTipoCampo() {
        return _sTipoCampo;
    }

    public void setsTipoCampo(String _sTipo) {
        this._sTipoCampo = _sTipo;
    }

    public String getsTipoPremisa() {
        return _sTipoPremisa;
    }

    public void setsTipoPremisa(String _sTipoPremisa) {
        this._sTipoPremisa = _sTipoPremisa;
    }

    public String toString(){
        String sCadena = "";
        sCadena += "IdRegla: " + _iIdRegla + "\n";
        sCadena += "IdPremisa: " + _iIdPremisa + "\n";
        sCadena += "TipoPremisa: " +  _sTipoPremisa + "\n";
        sCadena += "Tabla: " + _sTabla + "\n";
        sCadena += "Campo: " +  _sCampo + "\n";
        sCadena +=  "Valor: " + _sValor + "\n";
        sCadena +=  "ValorMin: " + _sValorMin + "\n";
        sCadena +=  "ValorMax: " + _sValorMax + "\n";
        return sCadena;
    }
}

